<?php
/**
 * 全网发布测试微信消息处理服务器
 *
 * Author: Zeon
 * Date: 2017/7/21
 * Time: 16:24
 * Created by PhpStorm.
 */
namespace App\Services\OpenWechat\Servers;

use App\Exceptions\ApiErrCode;
use App\Models\OpenWechat\Authorizer;
use App\Services\OpenWechat\AppFactory;
use App\Services\OpenWechat\Contracts\AppServer;
use App\Services\OpenWechat\Mock;
use EasyWeChat\Kernel\Messages\Text;
use EasyWeChat\Kernel\Support\Collection;
use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application;

/**
 *
 * @link https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318611&token=759050a94736563493be06a1219c319f3e68a284&lang=zh_CN - 全网发布说明
 *
 * Class PublicDebutTestServer
 * @package App\Services\OpenWechat\Servers
 */
class PublicDebutTestServer implements AppServer
{
    /** @var Application */
    private $app;

    /**
     * @inheritdoc
     * @return \Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function serve()
    {
        $this->app = (new AppFactory())->authorizerApp(Authorizer::PUBLIC_DEBUT_TEST_APPID);

        $server = $this->app->server;

        $server->push(function (array $message) {
            return $this->tryHandleMessage($message);
        });

        $response = $server->serve();

        info('public debug server handle this event message');

        return $response;
    }

    /**
     * @param array $message
     *
     * @return null|string
     * @throws \Exception
     */
    function tryHandleMessage(array $message)
    {
        try {
            return $this->handleMessageByType($message);
        } catch (\Exception $e) {
            if (config('app.debug')) {
                return $e->getMessage() . "|" . $e->getFile() . "|" . $e->getLine();
            }

            return $this->serverErrorResponse();
        }
    }

    /**
     *  处理微信用户触发的事件
     *
     * @param array $message
     *
     * @return null
     * @throws \Exception
     */
    private function handleMessageByType(array $message)
    {
        if (config('app.debug')) logger($message);

        switch ($message['MsgType']) {
            case 'event':
                return $this->handleDebutEventMessage($message);
            case 'text':
                return $this->handleDebutTextMessage($message);
            case 'image':
                break;
            case 'voice':
                break;
            case 'video':
                break;
            case 'location':
                break;
            case 'link':
                break;
            default:
                return $this->handleUnknownTypeMessage($message);
        }

        return $this->defaultMessageResponse($message);
    }

    /**
     * 全网发布 处理开放平台发布测试事件
     *
     * @param $message
     *
     * @return string
     */
    private function handleDebutEventMessage(array $message)
    {
        logger('OpenWechat Debut Test : event handler');
        logger($message['Event']);

        return $message['Event'] . 'from_callback';
    }

    /**
     *  全网发布 微信检测接入接口
     *
     * @param array $message
     *
     * @return mixed
     * @throws \Exception
     */
    private function handleDebutTextMessage(array $message)
    {
        logger('OpenWechat Debut Test : text message handler');
        logger($message['Content']);

        // 测试文本消息的回复能力
        if ($message['Content'] === 'TESTCOMPONENT_MSG_TYPE_TEXT') {
            return $message['Content'] . '_callback';
        }

        // 测试消息客服的回复能力
        if (str_contains($message['Content'], 'QUERY_AUTH_CODE')) {
            $api_message = $this->assembleStaffApiMessage($message['Content']);
            $this->sendDebutStaffMessage($api_message, $message['FromUserName']);
        }

        return '';
    }

    /**
     * @param string $content - QUERY_AUTH_CODE:$query_auth_code$
     *
     * @return string
     */
    private function assembleStaffApiMessage($content)
    {
        $query_auth_code = last(explode(':', $content));

        logger('$query_auth_code$ : ' . $query_auth_code);

        $api_message = $query_auth_code . '_from_api';

        return $api_message;
    }

    /**
     * 全网发布 客服消息接入能力检测
     *
     * @param $msg_string
     * @param $open_id
     *
     * @throws \Exception
     */
    private function sendDebutStaffMessage($msg_string, $open_id)
    {
        $text_msg = new Text($msg_string);

        $staff = $this->app->staff;

        $staff->message($text_msg)->to($open_id)->send();
    }

    /**
     * @param array $message
     *
     * @return null|string
     */
    private function handleUnknownTypeMessage(array $message)
    {
        $this->logUnknownTypeMessage($message);

        return null;
    }

    /**
     * @param array $message
     */
    private function logUnknownTypeMessage(array $message)
    {
        logger(ApiErrCode::LOG_PREFIX . self::class . ' unknown message type');

        logger($message);
    }

    /**
     * 默认消息类型处理
     *
     * @param array $message
     *
     * @return null|string
     */
    private function defaultMessageResponse(array $message)
    {
        if (config('app.debug')) {
            $this->logUnknownTypeMessage($message);

            return 'this is debut server';
        }

        return null;
    }

    /**
     * 服务出错返回的信息
     *
     * @return string
     */
    private function serverErrorResponse()
    {
        return '哦...服务器被外星人劫持了';
    }

    /**
     * 处理微信扫一扫 的扫码事件
     *
     * @param $message
     *
     * @return string|mixed
     */
    private function handleEventMessage($message)
    {
        switch ($message->Event) {

            // 扫码订阅或普通关注事件
            case 'subscribe':
                return $this->handleSubscribeEvent($message);

            // 纯粹的扫码事件
            case 'SCAN' :
//                return $this->handleScanEvent($message);

            // 自定义菜单的处理
            case 'CLICK':
//                return $this->customClickHandler($message);
                break;

            // 点击菜单 VIEW 也会触发回调事件
            case 'VIEW':
//                return $this->handleViewEvent($message);
                break;

            // 取关
            case 'unsubscribe':
                return $this->handleUnSubscribeEvent($message);

            // 地理位置
            case 'LOCATION' :
                return $this->handleLocationEvent($message);
                break;

            // 门店 WIFI 已连接
            case 'WifiConnected' :
//                return $this->handlePOIWifiConnectedEvent($message);
                break;

            // '其它事件';
            default:
                return null;
        }
    }

    /**
     * @param array $message
     *
     * @return mixed|null|string
     */
    private function handleSubscribeEvent(array $message)
    {
        if (! isset($message['EventKey'])) {
            //纯粹的关注事件;
            return $this->handlePureSubscribeEvent($message);
        } else {
            // 扫码关注事件
            return $this->processQrCodeScan($message);
        }
    }

    /**
     * 关注公众号，保存微信用户信息，返回关注公众号的信息
     *
     * @param array $message
     *
     * @see Mock::serverEventSubscribeMessage()
     *
     * @return mixed|string
     */
    private function handlePureSubscribeEvent(array $message)
    {
        return '欢迎关注全网发布测试服务器。';
    }

    /**
     * 处理微信用户扫码带的参数
     *
     * @param $message
     *
     * @see Mock::serverEventScanMessage()
     * @see Mock::serverEventScanSubscribeMessage()
     *
     * @return null|string
     */
    private function processQrCodeScan(array $message)
    {
        $scan_event_handler = null;

        return null;
    }

    /**
     * @param array $message
     *
     * @see Mock::serverEventUnSubscribeMessage()
     *
     * @return null
     */
    private function handleUnSubscribeEvent(array $message)
    {
        return null;
    }

    /**
     * @param $message
     *
     * @see Mock::serverEventLocationMessage()
     * @return string
     */
    private function handleLocationEvent($message)
    {
        logger('OpenWechat Debut Test : Location Event');

        return $message->Event . 'from_callback';
    }

    /**
     * 处理用户消息 | 关键字回复
     *
     * @param $message
     *
     * @see Mock::serverTextMessage()
     * @return mixed
     */
    private function handleTextMessage(Collection $message)
    {
        $keyword = $message->Content;

        if (config('app.debug')) return 'goat local test';

        return null;
    }

    /**
     * @param $message
     *
     * @return null|string
     */
    private function handleScanEvent(array $message)
    {
        return null;
    }
}